﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTO;

namespace DataAccessLayer
{
    using DataAccessLayer.Properties;
    using DataAccessLayer.Admin.Cache;
    using IMModel.Domain;

    partial class DTOConverter
    {
        public DTO.AdmRespondent CreateAdmRespondent(Respondent r)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DepartmentTerm depTerm = db.DepartmentTerms.Single(s => s.IDDepartmentTerm == r.IDDepartmentTerm);

                DTO.AdmRespondent admRespondent = new DTO.AdmRespondent
                {
                    IDRespondent = r.IDRespondent,
                    Person = this.CreateAdmPerson(db.Persons.First(f => f.IDPerson == r.IDPerson)),
                    Department = this.CreateAdmDepartment(db.Departments.First(f => f.IDDepartment == depTerm.IDDepartment)),
                    Job = this.CreateAdmJob(db.Jobs.First(f => f.IDJob == r.IDJob)),
                    IDTerm = depTerm.IDTerm,
                    FlagOsnJob = r.FlagOsnJob,
                    IgnoreVolumes = r.IgnoreVolumes,
                    Dismissed = r.Dismissed
                };
                return admRespondent;
            }
        }

        public DTO.AdmPersonDegree CreateAdmPersonDegree(PersonDegree p)
        {
            return new AdmPersonDegree
            {
                Person = CreateAdmPerson(p.Person),
                Degree = CreateAdmDegree(p.Degree),
                IDTerm = p.IDTerm,
                ID = p.ID
            };
        }

        public DTO.AdmDegree CreateAdmDegree(Degree d)
        {
            return new DTO.AdmDegree
            {
                ID = d.IDDegree,
                Name = d.Name
            };
        }

        public DTO.AdmRespondent CreateAdmRespondent_AnswerLog(Respondent r, Department d)
        {
            return new DTO.AdmRespondent
            {
                IDRespondent = r.IDRespondent,
                Person = DTOConverter.Instance.CreateAdmPerson(r.Person),
                Department = DTOConverter.Instance.CreateAdmDepartment_AnswerLog(d)
            };
        }

        public DTO.AdmDepartment CreateAdmDepartment(Department d, DepartmentTerm dt)
        {
            DTO.AdmDepartment admDepartment = new DTO.AdmDepartment
            {
                IDDepartment = d.IDDepartment,
                Name = d.Name,
                Abbriviation = d.Abbriviation,
                Childs = new List<DTO.DTOBase>(),
                IDTerm = dt.IDTerm,
                IDDepartmentTerm = dt.IDDepartmentTerm,
                DepartmentType = DTOConverter.Instance.CreateAdmDepartmentType(d.DepartmentType),
                FullName = DepartmentName.GetFullName(d)
            };
            return admDepartment;
        }

        public DTO.AdmDepartment CreateAdmDepartment_AnswerLog(Department d)
        {
            return new DTO.AdmDepartment
            {
                Name = d.Name,
                Abbriviation = d.Abbriviation
            };
        }

        public DTO.AdmDepartment CreateAdmDepartment(Department d)
        {
            return new DTO.AdmDepartment
            {
                IDDepartment = d.IDDepartment,
                Name = d.Name,
                Abbriviation = d.Abbriviation,
                Childs = new List<DTO.DTOBase>(),
                DepartmentType = DTOConverter.Instance.CreateAdmDepartmentType(d.DepartmentType),
                FullName = DepartmentName.GetFullName(d),
                SID = d.SID
            };
        }

        public DTO.AdmJob CreateAdmJob(Job j)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DTO.AdmJob admJob = new DTO.AdmJob
                {
                    IDJob = j.IDJob,
                    Position = this.CreateAdmPosition(db.Positions.First(f => f.IDPosition == j.IDPosition)),
                    Status = this.CreateAdmStatus(db.Status.First(f => f.IDStatus == j.IDStatus))
                };
                return admJob;
            }
        }

        public DTO.AdmPosition CreateAdmPosition(Position p)
        {
            DTO.AdmPosition admPosition = new DTO.AdmPosition
            {
                IDPosition = p.IDPosition,
                Name = p.Name,
                SID = p.SID,
                Order = p.Order,
                IsTotal = p.IsTotal
            };
            return admPosition;
        }

        public DTO.AdmStatus CreateAdmStatus(Status s)
        {
            DTO.AdmStatus admStatus = new DTO.AdmStatus
            {
                IDStatus = s.IDStatus,
                Order = s.Order
            };
            return admStatus;
        }

        public DTO.AdmPerson CreateAdmPerson(Person P)
        {
            DTO.AdmPerson admPerson = new DTO.AdmPerson
            {
                IDPerson = P.IDPerson,
                FirstName = P.FirstName,
                LastName = P.LastName,
                Patronymic = P.Patronymic,
                EMail = P.E_Mail,
                ShortFIO = P.LastName + " " + P.FirstName[0] + "." + P.Patronymic[0] + "."
            };

            return admPerson;
        }

        public DTO.AdmTerm CreateAdmTerm(Term t)
        {
            DTO.AdmTerm term = new DTO.AdmTerm
            {
                IDTerm = t.IDTerm,
                Order = t.Order,
                Founds = t.Founds,
                Start = t.Start,
                Stop = t.Stop,
                StartFill = t.StartFill,
                StopFill = t.StopFill,
                k1 = t.k1,
                k2 = t.k2,
                l1 = t.l1,
                l2 = t.l2
            };
            return term;
        }

        public DTO.AdmUnit CreateAdmUnit(Unit u, bool withStatistics)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DTO.AdmUnit unit = new DTO.AdmUnit
                {
                    IDUnit = u.IDUnit,
                    Name = u.Name
                };
                if(withStatistics == true)
                {
                    unit.CharacteristicsCount = db.CharacteristicTerms.Where(w => w.IDUnit == u.IDUnit).Count();
                }
                return unit;
            }
        }

        public DTO.AdmResponsible CreateAdmResponsible(Responsible r)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DTO.AdmResponsible resp = new DTO.AdmResponsible
                {
                    IDResponsible = r.IDResponsible,
                    Position = this.CreateAdmPosition(db.Positions.First(f => f.IDPosition == r.IDPosition))
                };
                // Department может быть = null
                if (r.IDDepartment != null)
                {
                    resp.Department = this.CreateAdmDepartment(db.Departments.First(f => f.IDDepartment == r.IDDepartment));
                }
                return resp;
            }

        }

        public DTO.AdmCharacteristic CreateAdmCharacteristic(Characteristic c)
        {
            return new DTO.AdmCharacteristic
            {
                ID = c.IDCharacteristic,
                Name = c.Name,
                Childs = new List<DTO.DTOBase>(),
                Responsibles = new List<DTO.AdmResponsible>()
            };
        }

        public DTO.AdmGradation CreateAdmGradation(Gradation g)
        {
            return new DTO.AdmGradation
            {
                ID = g.IDGradation,
                Name = g.Name,
                Childs = new List<DTO.DTOBase>(),
                Order = null
            };
        }

        public DTO.AdmCategory CreateAdmCategory(Category c)
        {
            return new DTO.AdmCategory
            {
                IDCategory = c.IDCategory,
                Name = c.Name,
                ImagePath = c.ImagePath
            };
        }

        public DTO.AdmSection CreateAdmSection(Section s)
        {
            return new DTO.AdmSection
            {
                ID = s.IDSection,
                Name = s.Name,
                Childs = new List<DTO.DTOBase>()
            };
        }

        public DTO.AdmCharacteristic CreateAdmCharacteristic(GetIndexMarkStructCache cache, Characteristic c, CharacteristicTerm charTerm)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                CategorySectionTerm catSecTerm = charTerm.CategorySectionTerm;

                Category category = (from ct in db.CategoryTerms
                                    join cat in db.Categories on ct.IDCategory equals cat.IDCategory
                                     where ct.IDCategoryTerm == catSecTerm.IDCategoryTerm
                                    select cat).Single();

                Unit unit = db.Units.Single(s => s.IDUnit == charTerm.IDUnit);

                Section section = (from st in db.SectionTerms
                                   join sec in db.Sections on st.IDSection equals sec.IDSection
                                   where st.IDSectionTerm == catSecTerm.IDSectionTerm
                                   select sec).Single();

                DTO.AdmCharacteristic characteristic = new DTO.AdmCharacteristic
                {
                    ID = c.IDCharacteristic,
                    Name = c.Name,
                    Order = charTerm.Order,
                    Section = this.CreateAdmSection(section, charTerm.IDTerm),
                    Weight = charTerm.Weight,
                    IDTerm = charTerm.IDTerm,
                    Visibility = charTerm.Visibility,
                    Childs = new List<DTO.DTOBase>(),
                    Responsibles = new List<DTO.AdmResponsible>(),
                    IDCharacteristicTerm = charTerm.IDCharacteristicTerm,
                    IndexRequired = charTerm.IndexRequired,
                    VolumeValidPeriod = charTerm.VolumeValidPeriod,
                    IDPrevCharacteristicTerm = charTerm.IDPrevCharacteristicTerm,
                    IDCategorySectionTerm = catSecTerm.ID
                };

                #region Поиск записей к кэше
                if (cache != null)
                {
                    DTO.AdmCategory cacheCat = cache.admCategories.Values.SingleOrDefault(x => x.IDCategory == category.IDCategory
                        && x.IDTerm == charTerm.IDTerm);
                    DTO.AdmUnit cacheUnit = cache.admUnit.Values.SingleOrDefault(x => x.IDUnit == unit.IDUnit);

                    #region Категории
                    if (cacheCat == null)
                    {
                        DTO.AdmCategory admCat = this.CreateAdmCategory(category, charTerm.IDTerm);
                        characteristic.Category = admCat;
                        cache.admCategories.Add(admCat.IDCategoryTerm, admCat);
                    }
                    else
                    {
                        characteristic.Category = cacheCat;
                    }
                    #endregion

                    #region Едиицы измерения
                    if (cacheUnit == null)
                    {
                        DTO.AdmUnit admUnit = this.CreateAdmUnit(unit, false);
                        characteristic.Unit = admUnit;
                        cache.admUnit.Add(unit.IDUnit, admUnit);
                    }
                    else
                    {
                        characteristic.Unit = cacheUnit;
                    }
                    #endregion
                }
                else
                {
                    characteristic.Category = this.CreateAdmCategory(category, charTerm.IDTerm);
                    characteristic.Unit = this.CreateAdmUnit(unit, false);

                }
                #endregion

                var responsibles = from cr in db.CharacteristicResponsibles
                                   join resp in db.Responsibles on cr.IDResponsible equals resp.IDResponsible
                                   where cr.IDCharacteristicTerm == charTerm.IDCharacteristicTerm
                                   select resp;
                foreach (Responsible responsible in responsibles)
                {
                    if (cache != null)
                    {
                        DTO.AdmResponsible cacheResp = cache.admResponsible.Values.SingleOrDefault(x => x.IDResponsible ==
                            responsible.IDResponsible);

                        if (cacheResp != null)
                        {
                            characteristic.Responsibles.Add(cacheResp);
                        }
                        else
                        {
                            DTO.AdmResponsible admResp = this.CreateAdmResponsible(responsible);
                            characteristic.Responsibles.Add(admResp);
                            cache.admResponsible.Add(responsible.IDResponsible, admResp);
                        }
                    }
                    else
                    {
                        characteristic.Responsibles.Add(this.CreateAdmResponsible(responsible));
                    }
                }
                return characteristic;
            }
        }

        public DTO.AdmCategory CreateAdmCategory(Category c, int IDTerm)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                CategoryTerm catTerm = db.CategoryTerms.First(f => f.IDCategory == c.IDCategory && f.IDTerm == IDTerm);

                DTO.AdmCategory category = new DTO.AdmCategory
                {
                    IDCategory = c.IDCategory,
                    Name = c.Name,
                    IDTerm = IDTerm,
                    Weight = catTerm.Weight,
                    ImagePath = c.ImagePath,
                    IDCategoryTerm = catTerm.IDCategoryTerm,
                    CharacteristicsCount = db.CharacteristicTerms.Where(w => w.CategorySectionTerm.IDCategoryTerm == catTerm.IDCategoryTerm).Count()
                };

                return category;
            }
        }

        public DTO.AdmSection CreateAdmSection(Section s, int IDTerm)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                SectionTerm secTerm = db.SectionTerms.First(f => f.IDSection == s.IDSection && f.IDTerm == IDTerm);

                DTO.AdmSection sec = new DTO.AdmSection
                {
                    ID = s.IDSection,
                    Name = s.Name,
                    Order = secTerm.Order,
                    //IDParentSection = secTerm.IDParentSection,
                    IDTerm = IDTerm,
                    Weight = secTerm.Weight,
                    Childs = new List<DTO.DTOBase>(),
                    IDSectionTerm = secTerm.IDSectionTerm,
                    Participate = secTerm.Participate
                };
                return sec;
            }
        }

        public DTO.AdmGradation CreateAdmGradation(GradationTerm gr)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                Gradation g = db.Gradations.Single(s => s.IDGradation == gr.IDGradation);
                DTO.AdmGradation grad = new DTO.AdmGradation
                {
                    ID = g.IDGradation,
                    Name = g.Name,
                    IDTerm = gr.IDTerm,
                    Weight = (gr.Weight ?? 0),
                    Childs = new List<DTO.DTOBase>(),
                    IDGradationTerm = gr.IDGradationTerm,
                    IDParentGradationTerm = gr.IDParentGradationTerm,
                    Order = gr.Order
                };

                if (gr.IDUnit != null)
                {
                    grad.Unit = CreateAdmUnit(gr.Unit, false);
                }

                return grad;
            }
        }

        // +
        public DTO.AdmAnswerLog CreateAdmAnswerLog(GetAnswerLogCache cache, Answer al)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DTO.AdmRespondent respondent = cache.admRespondents.SingleOrDefault(s => s.Key == al.IDRespondent).Value;
                DTO.AdmCharacteristic characteristic = cache.admCharacteristics.SingleOrDefault(s => s.Key == al.IDCharacteristicTerm).Value;

                if (respondent == null)
                {
                    Respondent tmp_resp = db.Respondents.Single(f => f.IDRespondent == al.IDRespondent);
                    respondent = DTOConverter.Instance.CreateAdmRespondent_AnswerLog(tmp_resp, tmp_resp.DepartmentTerm.Department);
                    cache.admRespondents.Add(al.IDRespondent, respondent);
                }
                if (characteristic == null)
                {
                    characteristic = DTOConverter.Instance.CreateAdmCharacteristic(al.CharacteristicTerm.Characteristic);
                    cache.admCharacteristics.Add(al.CharacteristicTerm.IDCharacteristicTerm, characteristic);
                }

                DTO.AdmAnswerLog item = new DTO.AdmAnswerLog();
                item.IDAnswer = al.IDAnswer;
                item.IDCharGrad = al.IDCharacteristicTerm;
                item.UserName = al.UserName;
                item.CurrentTime = al.DateTime;
                item.Characteristic = characteristic;
                item.Respondent = respondent;
                item.Gradations = new List<DTO.AdmGradationAnswerLog>();
                item.Volume = al.Volume;
                item.Childs = new List<DTO.AdmAnswerLog>();
                item.IDOldAnswer = al.IDOldAnswer;
                item.HaveChilds = (al.Answers.Count() > 0);
                // Присваиваем статус
                if (al.IDOldAnswer != null)
                {
                    if (al.IsDeleted == true)
                        item.Operation = DTO.AdmAnswerLogOperation.Deleted;
                    else
                        item.Operation = DTO.AdmAnswerLogOperation.Updated;
                }
                else
                {
                    item.Operation = DTO.AdmAnswerLogOperation.Created;
                }

                foreach (GradationsAnswer ga in al.GradationsAnswers)
                {
                    List<GradationTerm> trace = cache.trace.SingleOrDefault(s => s.Key == ga.IDGradationTerm).Value;
                    if (trace == null)
                    {
                        trace = new List<GradationTerm>();
                        SqlDataProvider.GetTrace(trace, ga.IDGradationTerm, ga.GradationTerm.IDTerm);
                        cache.trace.Add((int)ga.IDGradationTerm, trace);
                    }

                    DTO.AdmGradationAnswerLog Gradation = new DTO.AdmGradationAnswerLog();
                    Gradation.Volume = ga.Volume;
                    Gradation.Operation = item.Operation;
                    Gradation.IDAnswer = ga.IDAnswer;
                    Gradation.IDGradationTerm = ga.IDGradationTerm;
                    string GradationsStr = string.Empty;

                    // Отдельно заполняем некоторые поля
                    for (int i = trace.Count() - 1; i >= 0; --i)
                    {
                        // Если это группа - пропускаем
                        //if (trace.ElementAt(i).IDParentGradationTerm == null)
                        //{
                        //    continue;
                        //}

                        Gradation grad = db.Gradations.First(f => f.IDGradation == trace.ElementAt(i).IDGradation);
                        GradationsStr += grad.Name;
                        if (i - 1 >= 0) GradationsStr += "; ";
                    }
                    Gradation.GradationsStr = GradationsStr;
                    item.Gradations.Add(Gradation);
                }

                CharacteristicTerm charTerm = al.CharacteristicTerm;
                item.Characteristic.Order = charTerm.Order;
                item.Characteristic.Unit = DTOConverter.Instance.CreateAdmUnit(charTerm.Unit, false);

                return item;
            }
        }

        // +
        public DTO.AdmInputLog CreateAdmInputLog(InputLog log)
        {
            return new DTO.AdmInputLog
            {
                IDLog = log.IDLog,
                UserName = log.UserName,
                Date = log.Date
            };
        }

        // +
        public DTO.AdmDepartmentType CreateAdmDepartmentType(DepartmentType dt)
        {
            return new DTO.AdmDepartmentType
            {
                ID = dt.ID,
                Name = dt.Name
            };
        }
        
        public DTO.Money CreateMoneyStub(Respondent Resp)
        {
            return new Money
            {
                Premium = Math.Round(Resp.Premium, 2),
                Resp = DTOConverter.Instance.CreateResp(Resp)
            };
        }

        public DTO.SubscriberInfo CreateSubscriberInfo(Subscriber subs)
        {
            using (IMModel.Domain.IMDataDataContext db = new IMModel.Domain.IMDataDataContext(Settings.Default.IndexMarkConnectionString))
            {
                DTO.SubscriberInfo si = new DTO.SubscriberInfo();
                si.IDSubscriber = subs.IDSubscriber;
                si.SID = subs.SID;
                si.Email = subs.Email;
                si.IsActive = subs.IsActive;
                si.Respondents = new List<DTO.Respondent>();

                foreach (Subscribe subscribe in db.Subscribes.Where(x => x.IDSubscriber == subs.IDSubscriber))
                {
                    si.Respondents.Add(DTOConverter.Instance.CreateResp(subscribe.Respondent));
                }

                return si;
            }
        }
    }
}
